package cn.openea.perpartner.meily.web.service.logistics.businessModule;

import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.DateUtils;
import cn.openea.perpartner.meily.constant.CommonConstants;
import cn.openea.perpartner.meily.constant.enums.ExpressCompany;
import cn.openea.perpartner.meily.constant.enums.ExpressStatus;
import cn.openea.perpartner.meily.constant.enums.LogisticsModule;
import cn.openea.perpartner.meily.web.entity.LogisticsInfo;
import cn.openea.perpartner.meily.web.entity.ProvideSamplesSub;
import cn.openea.perpartner.meily.web.service.ILogisticsInfoService;
import cn.openea.perpartner.meily.web.service.IProvideSamplesSubService;
import cn.openea.perpartner.meily.web.service.logistics.LogisticsQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author ysk
 * @version 1.0.1
 * @Description 样品物流查询
 * @createTime 2023年05月10日 15:17:00
 */
@Slf4j
@Service(value = LogisticsModuleService.SAMPLES_LOGISTICS_QUERY)
public class SamplesLogisticsModuleService extends LogisticsModelAbstractService {

    @Resource
    private IProvideSamplesSubService samplesSubService;
    @Resource
    private LogisticsQuery logisticsQuery;
    @Resource
    private ILogisticsInfoService logisticsInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LogisticsInfo findByModuleId(String moduleId) {
        ProvideSamplesSub provideSamplesSub = Optional.ofNullable(samplesSubService.getById(moduleId))
                .orElseThrow(() -> new ServiceException("样品不存在"));
        LogisticsInfo logisticsInfo = logisticsQuery.findByModuleAndModuleId(LogisticsModule.SAMPLES, moduleId);
        if (logisticsInfo == null && "已发货".equals(provideSamplesSub.getOrderStatus())) {
            synchLogistics(provideSamplesSub,
                    ExpressCompany.getByCode(provideSamplesSub.getExpressCompanyCode()),
                    provideSamplesSub.getCourierNumber(),
                    provideSamplesSub.getConsigneePhoneNum(),
                    null
            );
            return logisticsQuery.findByModuleAndModuleId(LogisticsModule.SAMPLES, moduleId);
        }
        return logisticsInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void logisticsChange(ExpressCompany expressCompany, String id, String courierNumber) {
        ProvideSamplesSub provideSamplesSub = Optional.ofNullable(samplesSubService.getById(id))
                .orElseThrow(() -> new ServiceException("样品不存在"));
        String orderStatus = provideSamplesSub.getOrderStatus();
        // 判断用户的收货信息是否填写完成
        String msg = verifyReceiptInfo(provideSamplesSub);
        if (StringUtils.isNotBlank(msg)) {
            throw new ServiceException(msg, 201);
        }
        String oldOrderStatus = provideSamplesSub.getOrderStatus();
        if ("待支付".equals(oldOrderStatus)) {
            throw new ServiceException("用户未支付，不可发货", 201);
        }
        // 如果有物流代表改物流操作
        boolean actionShipment = StringUtils.isBlank(provideSamplesSub.getCourierNumber());
        String logisticsId = "";
        if (actionShipment && "!待发货".equals(orderStatus)) { // 发货
            throw new ServiceException("样品已经发货了,不可重复发货", 201);
        } else if (!actionShipment) { // 改物流
            if ("待发货".equals(orderStatus)) {
                throw new ServiceException("样品还未发货，请先发货", 201);
            }
            if ("已完成".equals(orderStatus)) {
                throw new ServiceException("改订单已完成，不可更改物流", 201);
            }
            if ("已评价".equals(orderStatus)) {
                throw new ServiceException("改订单已完成，不可更改物流", 201);
            }
            if ("已回收".equals(orderStatus)) {
                throw new ServiceException("名额已回收，不可发货", 201);
            }
            String oldCourierNumber = provideSamplesSub.getCourierNumber();
            // 如果物流公司与物流单号与之前的一致，则不需要更新
            if (oldCourierNumber.equals(courierNumber)) {
                throw new ServiceException("新的物流信息与旧的物流信息一致，无需更新！");
            }
            LogisticsInfo logisticsInfo = this.findByModuleId(id);
            if (logisticsInfo != null && ExpressStatus.isInTransport(logisticsInfo.getStatus())) {
                throw new ServiceException("样品已经在运输中，不可更改物流");
            }
            if (logisticsInfo != null) {
                logisticsId = logisticsInfo.getId();
            }
        }
        // 发货
        provideSamplesSub.setOrderStatus("已发货");
        provideSamplesSub.setDeliveryGoodsTime(DateUtils.getNow());
        provideSamplesSub.setCourierNumber(courierNumber);
        expressCompany = synchLogistics(provideSamplesSub,
                expressCompany,
                courierNumber,
                provideSamplesSub.getConsigneePhoneNum(),
                logisticsId
        );
        provideSamplesSub.setExpressCompanyCode(expressCompany.getCode());
        provideSamplesSub.setCourierName(expressCompany.getName());
        // 修改样品记录
        samplesSubService.updateById(provideSamplesSub);
        // 发送物流更改通知
        samplesSubService.logisticsChangeNotify(provideSamplesSub, actionShipment ?
                CommonConstants.LOGISTICS.DELIVERY_ACTION : CommonConstants.LOGISTICS.CHANGE_LOGISTICS_ACTION);
    }

    @Override
    public LogisticsInfo findRealTimeLogistics(String moduleId) {
        ProvideSamplesSub provideSamplesSub = Optional.ofNullable(samplesSubService.getById(moduleId))
                .orElseThrow(() -> new ServiceException("样品不存在"));
        LogisticsInfo logisticsInfo = checkEventuallyLogistics(LogisticsModule.SAMPLES, moduleId);
        if (logisticsInfo != null && logisticsInfo.isSing()) {
            // 这是最终的物流信息了，不可能还有更新
            return logisticsInfo;
        }
        // 同步物流到自己表里面
        synchLogistics(provideSamplesSub,
                ExpressCompany.getByCode(provideSamplesSub.getExpressCompanyCode()),
                provideSamplesSub.getCourierNumber(),
                provideSamplesSub.getConsigneePhoneNum(),
                logisticsInfo != null ? logisticsInfo.getId() : null
        );
        return logisticsQuery.findByModuleAndModuleId(LogisticsModule.SAMPLES, moduleId);
    }

    @Override
    public void businessStatusSync(LogisticsInfo logisticsInfo) {
        if (StringUtils.isBlank(logisticsInfo.getId()) || StringUtils.isBlank(logisticsInfo.getModuleId())) {
            throw new ServiceException("物流Id和业务模块Id不能为空");
        }
        ProvideSamplesSub provideSamplesSub = Optional.ofNullable(samplesSubService.getById(logisticsInfo.getModuleId()))
                .orElseThrow(() -> new ServiceException("样品不存在"));
        if (provideSamplesSub.businessCompletion()) {
            // 业务完成
            logisticsInfoService.updateBusinessStatus(logisticsInfo.getId(), CommonConstants.LOGISTICS.BUSINESS_FINISH);
        }
    }


    @Override
    public void businessStatusFinish(String id) {
        Optional.ofNullable(samplesSubService.getById(id))
                .orElseThrow(() -> new ServiceException("样品不存在"));
        samplesSubService.businessStatusFinish(id);
    }

    /**
     * 判断用户的收货信息是否填写完成
     *
     * @param samplesSub
     * @return
     */
    private String verifyReceiptInfo(ProvideSamplesSub samplesSub) {
        if (StringUtils.isBlank(samplesSub.getConsigneeName())) {
            return "收货人姓名未填写";
        }
        if (StringUtils.isBlank(samplesSub.getConsigneePhoneNum())) {
            return "收货人手机号码未填写";
        }
        if (StringUtils.isBlank(samplesSub.getConsigneeAddress())) {
            return "收货地址未填写";
        }
        return "";
    }
}
